package com.ls.hnks.service.impl;

import cn.dev33.satoken.secure.SaSecureUtil;
import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ls.hnks.util.Result;
import com.ls.hnks.common.constant.RoleConstant;
import com.ls.hnks.mapper.UserMapper;
import com.ls.hnks.model.User;
import com.ls.hnks.model.UserGroup;
import com.ls.hnks.model.UserReservedPhone;
import com.ls.hnks.model.vo.UserDetailsVo;
import com.ls.hnks.service.UserGroupService;
import com.ls.hnks.service.UserReservedPhoneService;
import com.ls.hnks.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;

import static com.ls.hnks.util.ResultCodeEnum.AUTH_FAIL;

/**
 * @author 15375
 * @description 针对表【tb_user(用户表)】的数据库操作Service实现
 * @createDate 2023-01-25 21:58:36
 */
@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User>
        implements UserService{

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private UserReservedPhoneService userReservedPhoneService;

    @Autowired
    private UserGroupService userGroupService;


    @Override
    public Result loginByPassword(String phone, String pwd) {
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.eq("phone", phone);
        userQueryWrapper.eq("password", SaSecureUtil.sha1(pwd));
        User user = userMapper.selectOne(userQueryWrapper);
        if (user == null) {
            return Result.error(AUTH_FAIL);
        }
        // 第1步，先登录上
        StpUtil.login(user.getId());
        // 第2步，获取 Token  相关参数
        SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
        // 第3步，返回给前端
        return Result.ok(tokenInfo);
    }


    @Override
    public Result getSelfInfo(String  userId) {
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        // 排除password和num字段
        userQueryWrapper.select(User.class,
                fieldInfo -> !fieldInfo.getColumn().equals("password")
                        && !fieldInfo.getColumn().equals("num"));
        userQueryWrapper.eq("id",userId);
        User user = userMapper.selectOne(userQueryWrapper);
        return Result.ok(user);
    }

    @Override
    public Result getGroupMember(String userId) {
        User user = this.getById(userId);
        Integer groupID = user.getGroupid();
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        // 只查询 "id","name","phone","icon" 字段
        userQueryWrapper.select("id","name","phone","icon");
        userQueryWrapper.eq("groupId", groupID);
        userQueryWrapper.orderByAsc("num");
        List<User> users = userMapper.selectList(userQueryWrapper);
        return Result.ok(users);
    }

    @Override
    public Result getUserByPage(Integer pageNo, Integer size) {
        Page<User> page = new Page<>(pageNo, size);
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        // 只查询 "id","name","phone","icon","groupID" ,"right" 字段
        userQueryWrapper.select("id","name","phone","icon","groupID","`right`");
        userQueryWrapper.orderByAsc("num");
        IPage<User> userPage = userMapper.selectPage(page, userQueryWrapper);
        List<User> userList = userPage.getRecords();
        List<Integer> groupIDList = userList.stream().map(User::getGroupid).collect(Collectors.toList());
        List<UserGroup> userGroupList = userGroupService.list(
                new LambdaQueryWrapper<UserGroup>()
                        .in(UserGroup::getId, groupIDList)
        );
        HashMap<Integer, String > groupID2NameMap = userGroupList.stream().collect(HashMap::new, (m, v) -> m.put(v.getId(), v.getName()), HashMap::putAll);
        userList.forEach(item -> item.setGroupName(groupID2NameMap.get(item.getGroupid())));
        return Result.ok(userPage);
    }

    @Override
    public Result getDetails(String id) {
        UserDetailsVo userDetailsVo = new UserDetailsVo();
        User user = this.getById(id);
        List<UserReservedPhone> userReservedPhones = userReservedPhoneService.getContractsByUserId(id);
        BeanUtils.copyProperties(user,userDetailsVo);
        userDetailsVo.setUserReservedPhoneList(userReservedPhones);
        return Result.ok(userDetailsVo);
    }

    @Transactional
    @Override
    public void saveUser(User user) {
        int createUserId = Integer.parseInt(StpUtil.getLoginId().toString());
        user.setCreateuserid(createUserId);
        user.setRight(RoleConstant.USER);
        user.setNum(this.count()+1);
        user.setPassword(SaSecureUtil.sha1(user.getPassword() == null ? "123456" : user.getPassword()));
        this.save(user);
        List<UserReservedPhone> userReservedPhoneList = user.getUserReservedPhoneList();
        if(userReservedPhoneList != null && userReservedPhoneList.size() > 0) {
            for (UserReservedPhone userReservedPhone : userReservedPhoneList) {
                userReservedPhone.setUserid(user.getId());
                userReservedPhone.setCreateuserid(createUserId);
            }
            userReservedPhoneService.saveBatch(userReservedPhoneList);
        }
    }

    @Transactional
    @Override
    public void removeUser(String id) {
//        userReservedPhoneService.remove(
//                new LambdaQueryWrapper<UserReservedPhone>()
//                        .eq(UserReservedPhone::getUserid,id)
//        );
        this.removeById(id);
    }

    @Override
    public List<User> getExperienceAccount() {
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.select("phone,password");
        userQueryWrapper.eq("other","experienceAccount");
        userQueryWrapper.last("limit 10");
        return this.list(userQueryWrapper);
    }
}




